/**
 * @file printf.c
 * @date 23.04.25
 * @author xin
 * @brief 打印相关操作
 * @version 0.1
 * @status Stable
*/

/*
    暂时剔除printf()/printfinit()/panic()中用到锁的代码
*/

#include <stdarg.h>
#include "types.h"
#include "defs.h"

// 是否在panic中
volatile int panicked = 0;

// 0~f数字字符
static char digits[] = "0123456789abcdef";

/**
 * @brief 打印整数
 * @param xx 待打印的整数
 * @param base 进制，2/8/16/10
 * @param sign 是否计符号
*/
static void 
printint(int xx, int base, int sign)
{
    char buf[16];
    int i;
    uint x;

    if (sign && (sign = xx < 0)) x = -xx;
    else x = xx;

    i = 0;
    do
    {
        buf[i++] = digits[x % base];
        x /= base;
    } while (x != 0);
    
    if (sign) buf[i++] = '-';

    while (i-- > 0) consputc(buf[i]);
}

/**
 * @brief 打印指针
 * @param x 待打印的指针
*/
static void
printptr(uint64 x)
{
    int i;
    consputc('0');
    consputc('x');
    for (i = 0; i < sizeof(uint64) * 2; i++, x <<= 4)
        // digits[x >> (64 - 4)]
        consputc(digits[x >> (sizeof(uint64) * 8 - 4)]);
}

void 
printfinit(void)
{
    // 暂未使用多个进程，所以暂未调用锁，初始化为空
}

void
printf(char *fmt, ...)
{
    va_list ap;
    int i, c;
    char *s;

    if (fmt == 0) panic("null fmt");

    va_start(ap, fmt);
    for (i = 0; (c = fmt[i] & 0xff) != 0; i++) {
        if (c != '%') {
            consputc(c);
            continue;
        }
        c = fmt[++i] & 0xff;
        if (c == 0) break;
        switch(c) {
        case 'd':
            printint(va_arg(ap, int), 10, 1);
            break;
        case 'x':
            printint(va_arg(ap, int), 16, 1);
            break;
        case 'p':
            printptr(va_arg(ap, uint64));
            break;
        case 'c':
            consputc(va_arg(ap, uint));
            break;
        case 's':
            if ((s = va_arg(ap, char*)) == 0) s = "(null)";
            while (*s != 0) {
                consputc(*s);
                s++;
            }
            break;
        case '%':
            consputc('%');
            break;
        default:
            // 不可识别的格式化形式，直接打印%后面的字符
            consputc('%');
            consputc(c);
            break;
        }
    }
    va_end(ap);
}

void
panic(char *s)
{
    printf("panic: ");
    printf(s);
    printf("\n");
    
    while(1);
}